home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / STRINGS / OPUNIQ / OPTREE.PAS next >
Pascal/Delphi Source File  |  1990-10-25  |  5KB  |  229 lines

  1. {$S-,R-,V-,I-,B-,F+,O-,A-}
  2.  
  3. {Updated 10/24/90 to add a Remove method to the Tree object}
  4.  
  5. unit OpTree;
  6.   {-Binary tree object}
  7.  
  8. interface
  9.  
  10. uses
  11.   OpString, OpRoot;
  12.  
  13. type
  14.   TreeNodePtr = ^TreeNode;
  15.   TreeNode =
  16.     object(Root)
  17.       tnLeft, tnRight : TreeNodePtr; {Pointers to children}
  18.       constructor Init;
  19.         {-Initialize children to nil}
  20.     end;
  21.  
  22.   TreePtr = ^Tree;
  23.   TreeActionProc = procedure (N : TreeNodePtr; T : TreePtr);
  24.   Tree =
  25.     object(Root)
  26.       trRoot : TreeNodePtr;
  27.  
  28.       constructor Init;
  29.         {-Create an empty tree}
  30.       destructor Done; virtual;
  31.         {-Dispose of entire tree}
  32.       procedure Clear;
  33.         {-Dispose of all elements of tree}
  34.       function Empty : Boolean;
  35.         {-Return True if Tree is empty}
  36.       procedure Insert(N : TreeNodePtr);
  37.         {-Insert a new node into tree}
  38.       procedure Remove(N : TreeNodePtr);
  39.         {-Remove an existing node from tree}
  40.       function Find(Key : Pointer) : TreeNodePtr;
  41.         {-Return a pointer to TreeNode having a key pointed to by Key}
  42.       procedure VisitNodesUp(Action : TreeActionProc);
  43.         {-Visit all nodes in ascending order and call Action procedure}
  44.  
  45.       {-- methods to be overridden by descendants --}
  46.       function Compare(Key1, Key2 : Pointer) : CompareType; virtual;
  47.         {-Compare two keys, returning Less, Equal, Greater}
  48.       function GetKey(N : TreeNodePtr) : Pointer; virtual;
  49.         {-Return a pointer to the key value for node N}
  50.     end;
  51.  
  52.   {====================================================================}
  53.  
  54. implementation
  55.  
  56. constructor TreeNode.Init;
  57.   {-Initialize children to nil}
  58. begin
  59.   if not Root.Init then
  60.     Fail;
  61.   tnLeft := nil;
  62.   tnRight := nil;
  63. end;
  64.  
  65.   {--------------------------------------------------------------------}
  66.  
  67. constructor Tree.Init;
  68.   {-Create an empty tree}
  69. begin
  70.   if not Root.Init then
  71.     Fail;
  72.   trRoot := nil;
  73. end;
  74.  
  75. destructor Tree.Done;
  76.   {-Dispose of entire tree}
  77. begin
  78.   Clear;
  79. end;
  80.  
  81. procedure DeleteNode(N : TreeNodePtr; T : TreePtr);
  82.   {-Dispose of node N}
  83. begin
  84.   Dispose(N, Done);
  85. end;
  86.  
  87. procedure Tree.Clear;
  88.   {-Dispose of all elements of tree}
  89. begin
  90.   VisitNodesUp(DeleteNode);
  91. end;
  92.  
  93. function Tree.Empty : Boolean;
  94.   {-Return True if Tree is empty}
  95. begin
  96.   Empty := (trRoot = nil);
  97. end;
  98.  
  99. procedure Tree.Insert(N : TreeNodePtr);
  100.   {-Insert a new node into tree}
  101. var
  102.   Key : Pointer;
  103.  
  104.   procedure Visit(var P : TreeNodePtr);
  105.     {-Visit node P and its children}
  106.   begin
  107.     if P = nil then
  108.       {Link new node into tree}
  109.       P := N
  110.     else
  111.       case Compare(Key, GetKey(P)) of
  112.         Less :
  113.           Visit(P^.tnLeft);
  114.         Greater :
  115.           Visit(P^.tnRight);
  116.         Equal :
  117.           {Already in tree, do nothing} ;
  118.       end;
  119.   end;
  120.  
  121. begin
  122.   Key := GetKey(N);
  123.   Visit(trRoot);
  124. end;
  125.  
  126. procedure Tree.Remove(N : TreeNodePtr);
  127.   {-Remove an existing node from tree}
  128. var
  129.   Key : Pointer;
  130.  
  131.   procedure Visit(var P : TreeNodePtr);
  132.     {-Visit node P and its children}
  133.  
  134.     procedure Rem(var R : TreeNodePtr);
  135.       {-Find leftmost node of right subtree and replace P with it}
  136.     begin
  137.       if R^.tnRight <> nil then
  138.         Rem(R^.tnRight)
  139.       else begin
  140.         R^.tnRight := P^.tnRight;
  141.         P := R;
  142.       end;
  143.     end;
  144.  
  145.   begin
  146.     if P = nil then
  147.       {Node is not in tree, do nothing}
  148.     else
  149.       case Compare(Key, GetKey(P)) of
  150.         Less :
  151.           Visit(P^.tnLeft);
  152.         Greater :
  153.           Visit(P^.tnRight);
  154.         Equal :
  155.           {Found node to delete}
  156.           if P^.tnRight = nil then
  157.             {Replace P with its left child}
  158.             P := P^.tnLeft
  159.           else if P^.tnLeft = nil then
  160.             {Replace P with its right child}
  161.             P := P^.tnRight
  162.           else
  163.             {Replace P with leftmost node of right subtree}
  164.             Rem(P^.tnLeft);
  165.       end;
  166.   end;
  167.  
  168. begin
  169.   Key := GetKey(N);
  170.   Visit(trRoot);
  171. end;
  172.  
  173. function Tree.Find(Key : Pointer) : TreeNodePtr;
  174.   {-Return a pointer to TreeNode having a key pointed to by Key}
  175.  
  176.   procedure Visit(N : TreeNodePtr);
  177.     {-Visit node N and its children}
  178.   begin
  179.     if N = nil then
  180.       Find := nil
  181.     else
  182.       case Compare(Key, GetKey(N)) of
  183.         Less :
  184.           Visit(N^.tnLeft);
  185.         Greater :
  186.           Visit(N^.tnRight);
  187.         Equal :
  188.           Find := N;
  189.       end;
  190.   end;
  191.  
  192. begin
  193.   Visit(trRoot);
  194. end;
  195.  
  196. procedure Tree.VisitNodesUp(Action : TreeActionProc);
  197.   {-Visit all nodes in ascending order and call Action procedure}
  198.  
  199.   procedure VisitUp(N : TreeNodePtr);
  200.     {-Visit node N and its children}
  201.   var
  202.     R : TreeNodePtr;
  203.   begin
  204.     if N <> nil then begin
  205.       R := N^.tnRight;
  206.       VisitUp(N^.tnLeft);
  207.       Action(N, @Self);
  208.       VisitUp(R);
  209.     end;
  210.   end;
  211.  
  212. begin
  213.   VisitUp(trRoot);
  214. end;
  215.  
  216. function Tree.Compare(Key1, Key2 : Pointer) : CompareType;
  217.   {-Compare two keys, returning Less, Equal, Greater}
  218. begin
  219.   Compare := Equal;
  220. end;
  221.  
  222. function Tree.GetKey(N : TreeNodePtr) : Pointer;
  223.   {-Return a pointer to the key value for node N}
  224. begin
  225.   GetKey := nil;
  226. end;
  227.  
  228. end.
  229.